package compiler;
import compiler.error.CNoMemberError;
import compiler.error.CReMemberError;

/*
 *
 * CType
 *
 */
abstract class CType extends CSymbol
{
	int size;
	CType(int l) { super(l); }

	int GetSize() { return size; }
	int GetTypeId() { return 0; }
	CType GetType() { return this; }
}



class CArrayType extends CType
{
	int lo, hi;
	CType baseType;
	CType GetBaseType() { return baseType; }
	CArrayType(int l, int low, int high, CType bt)
	{
		super(l);
		baseType = bt;
		lo = low;
		hi = high;
		size = baseType.GetSize() * (hi - lo + 1);
	}
	public String toString()
	{
		return "Array [" + lo + ", " + hi + "] (Level "+ level + ") OF " + baseType.toString();
	}
}


class CBooleanType extends CType
{
	CBooleanType()
	{
		super(0); size = 1;
	}

	int GetTypeId() { return 2; }
	public String toString()
	{
		return "Boolean type (Level "+ level + ");";
	}
}


class CIntType extends CType
{
	CIntType()
	{
		super(0); size = 1;
	}

	int GetTypeId() { return 1; }
	public String toString()
	{
		return "Integer type (Level "+ level + ");";
	}
}

class CDoubleType extends CType
{
	CDoubleType()
	{
		super(0);size = 2;
	}
	
	int GetTypeId()	{ return 3; }
	public String toString()
	{
		return "Double type (Level " + level + ");";
	}
	
}

class CRecordType extends CType
{
	CRecordItem first;

	CRecordType(int l)
	{
		super(l);
		size = 0;
	}

	void AddItem(String n, CType it) throws CReMemberError
	{

		CRecordItem item = first;
		while (item != null)
		{
			if (item.name.equals(n)) throw new CReMemberError(n);
			item = item.next;
		}
		item = new CRecordItem(n, it, size);
		size += it.GetSize();
		item.next = first;
		first = item;
	}

	CRecordItem GetItem(String n) throws CNoMemberError
	{
		CRecordItem item = first;
		while (item != null)
		{
			if (item.name.equals(n)) return item;
			item = item.next;
		}
		throw new CNoMemberError(n);
	}

	public String toString()
	{
		return "Record type (Size = " + size + ")(Level "+ level + ")";
	}
}


class CRecordItem
{
	int offset;
	String name;
	private CType type;
	CRecordItem next;
	CRecordItem(String n, CType it, int o)
	{
		name = n; type = it; offset = o;
	}
	CType GetType() { return type; }
}


class CArgument
{
	CType type;
	boolean varTag;
	CType GetType() {return type; }
	CArgument(boolean b, CType t)
	{
		varTag = b; type = t;
	}
}

class CCloneType extends CType
{
	CType baseType;
	CCloneType(int l, CType t)
	{
		super(l); baseType = t.GetType();
	}
	CType GetType() { return baseType; }

	public String toString()
	{
		return baseType.toString();
	}
}


